#ifndef SUBDIVIDER_H

//--------------------------------------------------------
//		DEFINITIONS
//--------------------------------------------------------
#define SUBDIVIDER_H


//--------------------------------------------------------
//		INCLUDES
//--------------------------------------------------------
#include <vector>
#include "ModelFrame.h"
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include "util.h"

enum Sharpness { NO_SHARPNESS, ONE_EDGE, CREASE, CORNER, ONE_EDGE_BOUNDARY };
#define FACE_VERTEX		4
#define VERTEX_VERTEX	5
#define EDGE_VERTEX		6


//--------------------------------------------------------
//		TYPEDEFS
//--------------------------------------------------------
typedef PolyMesh::Point				Point;
typedef PolyMesh::VertexHandle		VHandle;
typedef PolyMesh::FaceHandle		FHandle;
typedef PolyMesh::HalfedgeHandle	HHandle;
typedef PolyMesh::EdgeHandle		EHandle;

typedef PolyMesh::FaceHalfedgeIter	FHIter;
typedef PolyMesh::VertexVertexIter	VVIter;
typedef PolyMesh::VertexEdgeIter	VEIter;
typedef PolyMesh::VertexFaceIter	VFIter;
typedef PolyMesh::VertexIter		VIter;
typedef PolyMesh::FaceIter			FIter;
typedef PolyMesh::EdgeIter			EIter;
typedef PolyMesh::FaceEdgeIter		FEIter;
typedef PolyMesh::FaceVertexIter	FVIter;

typedef PolyMesh::VertexData		VData;
typedef PolyMesh::FaceData			FData;
typedef PolyMesh::EdgeData			EData;


//--------------------------------------------------------
//		CLASS: SubdivisionScheme
//--------------------------------------------------------
class Subdivider
{
public:

	enum Scheme {LOOP, CATMULL};

	//Construction/destruction
	Subdivider(); 
	~Subdivider(){}

	virtual void showConnectivity ( const Selection* s ) = 0;
	virtual void showWeights	  ( const Selection* s ) = 0;

	virtual void subdivide	( ModelFrame* frame )
	{
		frame->numSubdivs++;
	}

	void updateImportanceMesh		  ( ModelFrame* frame );
	void clearSharpEdges			  ( ModelFrame* frame );
	void clearWeights				  ( PolyMesh*  mesh, PolyMesh* = NULL);

protected:

	// These are just accessible to classes that inherit from Subdivider

	void	  prepare				  ( PolyMesh**, PolyMesh**, PolyMesh** );	// initialize memory and internal meshes	  
	void	  cleanup				  ( PolyMesh**, PolyMesh**, PolyMesh** );	// cleanup any memory used in subdivision	  
	void	  setSharpnessInSubdivided( FHandle& fh );
	bool	  isSharp				  ( PolyMesh*, VHandle&, VHandle& );
	Sharpness isSharp				  ( PolyMesh*m, VHandle& vh );
	PolyMesh::Point	doVertexBoundary  ( PolyMesh*m, VHandle& vh, bool=false);


	Vec4f coarseVertexColor;
	Vec4f connectedVertexColor;
	Vec4f sharpEdgeColor;

	PolyMesh* mesh;			 // temporarily stores coarse mesh during subdivision  
	PolyMesh* connMesh;		 // is loaded with connectivity mesh during subdivision 
	PolyMesh* subMesh;		 // is loaded with subdivided mesh during subdivision   

	// temporary mesh properties added to mesh and used during subdivision, then removed:
	OpenMesh::VPropHandleT< PolyMesh::VertexHandle > subV_V;  // subdivided mesh vertex-vertex handle 
	OpenMesh::VPropHandleT< PolyMesh::VertexHandle > connV_V; // connected mesh vertex-vertex handle  
	OpenMesh::EPropHandleT< PolyMesh::VertexHandle > connE_V; // connected mesh edge-vertex handle    
	OpenMesh::EPropHandleT< PolyMesh::VertexHandle > subE_V;  // subdivided mesh edge-vertex handle  
	OpenMesh::FPropHandleT< PolyMesh::VertexHandle > connF_V; // connectivity mesh face-vertex handle 
	OpenMesh::FPropHandleT< PolyMesh::VertexHandle > subF_V;  // subdivided mesh face-vertex handle   
};

#endif